/*
JETware Hands-free Extension provides additional features for Windows Mobile HFP support.
Copyright (C) 2004-2009 Jim Thatcher

This program is free software; you can redistribute it and/or modify it under the terms of the 
GNU General Public License as published by the Free Software Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; 
if not, write to the Free Software Foundation, Inc., 
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Source Control header

$Workfile: ConfigRegSettings.cpp $
$Revision: 1 $
$Date: 1/1/09 1:11p $
*/
// Include the proper version of TAPI
#include <windows.h>
#include "JetBTConfig.h"
// #include "version.h"
#include "Ce_setup.h"
#include "shellapi.h"
#include "shlobj.h"
// #include "service.h"
typedef HANDLE _GetServiceHandle(LPWSTR szPrefix, LPWSTR szDllName, DWORD pdwDllBuf);
typedef HANDLE _RegisterService( LPCWSTR lpszType, DWORD dwIndex, LPCWSTR lpszLib,DWORD dwInfo);
typedef HANDLE _ActivateService(LPCWSTR lpszDevKey, DWORD dwClientInfo);
typedef BOOL _DeregisterService(HANDLE hDevice);

// TCHAR * g_szExtChainDll = NULL;
WORD g_wDebugLevels = 0;
TCHAR * g_szContactFilter = NULL;
BOOL  g_bIncludeNoCat = FALSE;
DWORD g_dwIncludeFax = 0;
DWORD g_dwMaxContacts[5] = {NO_LIMIT,NO_LIMIT,NO_LIMIT,NO_LIMIT,NO_LIMIT};
DWORD g_dwInvertRoam = 0;
DWORD g_dwInCallInterval = 2000;
DWORD g_dwIdleInterval = 5000;
DWORD g_dwReportIMI = 2;
// Options to select built-in, local, or combined handling of certain commands and reporting
DWORD g_dwHandleCMER = CMD_BOTH;
DWORD g_dwHandleCIND = CMD_BOTH;
DWORD g_dwHandleCLIP = CMD_INTERNAL_ONLY;
DWORD g_dwHandleCHUP = CMD_BOTH;
DWORD g_dwHandleCKPD = CMD_INTERNAL_ONLY;
DWORD g_dwHandleCPBS = CMD_LOCAL_ONLY;
DWORD g_dwHandleCPMS = CMD_LOCAL_ONLY;
DWORD g_dwFeatureMask = 0;
DWORD g_dwInBandRing = 0;
DWORD g_dwSleepOnDisconnect = 0;

TCHAR g_szIMEI[32];
TCHAR g_szActCode[16];
TCHAR * g_szMsgStore[2] = {NULL, NULL};
DWORD g_dwMsgMax[2] = {25,25};
BOOL g_bAllMsgs[2] = {FALSE,FALSE};

TCHAR * g_szMsgStoreNew[2] = {NULL, NULL};
DWORD g_dwMsgMaxNew[2] = {0,0};
BOOL g_bAllMsgsNew[2] = {FALSE,FALSE};

TCHAR * g_szMfrString = NULL;
TCHAR * g_szModelString = NULL;

void WriteCategories(TCHAR * szCatList)
{
    HRESULT hr                  = S_OK;
    HKEY    hKey                = NULL;
    DWORD   dwType              = 0;
	DWORD	dwSize				= 0;
	DWORD	dwValue				= 0;
	TCHAR	szValue[2048];

    if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, JETWARE_KEY, 0, NULL, 0, 0, NULL, &hKey, &dwType))
	{
		if ((szCatList != NULL) && (szCatList[0] != 0))
		{
			wsprintf(szValue, _T("%ls"), szCatList);
			RegSetValueEx(hKey, PBFILTER, 0, REG_SZ, (LPBYTE) &szValue, (lstrlen(szValue) + 1)*sizeof(TCHAR));
		}
		else
			RegDeleteValue(hKey, PBFILTER);
		if (g_bIncludeNoCat)
		{
			dwValue = g_bIncludeNoCat;
			RegSetValueEx(hKey, INCLUDE_NOCAT, 0, REG_DWORD, (LPBYTE) &dwValue, sizeof(DWORD));
		}
		else
			RegDeleteValue(hKey, INCLUDE_NOCAT);
		RegCloseKey(hKey);
	}

}

void WriteAdvancedSettings()
{
    HRESULT hr                  = S_OK;
    HKEY    hKey                = NULL;
    DWORD   dwType              = 0;
	DWORD	dwSize				= 0;
	DWORD	dwValue				= 0;

    if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, JETWARE_KEY, 0, NULL, 0, 0, NULL, &hKey, &dwType))
	{
		if (g_dwIncludeFax)
			RegSetValueEx(hKey, PBINCLUDE_FAX, 0, REG_DWORD, (LPBYTE) &g_dwIncludeFax, sizeof(DWORD));
		else
			RegDeleteValue(hKey, PBINCLUDE_FAX);

		if (g_dwMaxContacts[CONTACTS_ME] != NO_LIMIT)
			RegSetValueEx(hKey, PBLIMIT_ME, 0, REG_DWORD, (LPBYTE) &g_dwMaxContacts[CONTACTS_ME], sizeof(DWORD));
		else
			RegDeleteValue(hKey, PBLIMIT_ME);

		if (g_dwMaxContacts[CONTACTS_SM] != NO_LIMIT)
			RegSetValueEx(hKey, PBLIMIT_SM, 0, REG_DWORD, (LPBYTE) &g_dwMaxContacts[CONTACTS_SM], sizeof(DWORD));
		else
			RegDeleteValue(hKey, PBLIMIT_SM);

		if (g_dwMaxContacts[CONTACTS_DC] != NO_LIMIT)
			RegSetValueEx(hKey, PBLIMIT_DC, 0, REG_DWORD, (LPBYTE) &g_dwMaxContacts[CONTACTS_DC], sizeof(DWORD));
		else
			RegDeleteValue(hKey, PBLIMIT_DC);

		if (g_dwMaxContacts[CONTACTS_RC] != NO_LIMIT)
			RegSetValueEx(hKey, PBLIMIT_RC, 0, REG_DWORD, (LPBYTE) &g_dwMaxContacts[CONTACTS_RC], sizeof(DWORD));
		else
			RegDeleteValue(hKey, PBLIMIT_RC);

		if (g_dwMaxContacts[CONTACTS_MC] != NO_LIMIT)
			RegSetValueEx(hKey, PBLIMIT_MC, 0, REG_DWORD, (LPBYTE) &g_dwMaxContacts[CONTACTS_MC], sizeof(DWORD));
		else
			RegDeleteValue(hKey, PBLIMIT_MC);
		RegCloseKey(hKey);
	}
}

void WriteMessageSettings()
{
    HRESULT hr                  = S_OK;
    HKEY    hKey                = NULL;
    DWORD   dwType              = 0;
	DWORD	dwSize				= 0;
	DWORD	dwValue				= 0;

    if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, JETWARE_KEY, 0, NULL, 0, 0, NULL, &hKey, &dwType))
	{
		TCHAR szProvider[64];
		DWORD dwSize = 0;

		if (g_bAllMsgsNew[MESSAGES_ME] != g_bAllMsgs[MESSAGES_ME])
		{
			RegSetValueEx(hKey, ME_ALL_MSGS, 0, REG_DWORD, (LPBYTE) &g_bAllMsgsNew[MESSAGES_ME], sizeof(DWORD));
			g_bAllMsgs[MESSAGES_ME] = g_bAllMsgsNew[MESSAGES_ME];
		}

		if (g_dwMsgMaxNew[MESSAGES_ME] != g_dwMsgMax[MESSAGES_ME])
		{
			RegSetValueEx(hKey, ME_MSG_MAX, 0, REG_DWORD, (LPBYTE) &g_dwMsgMaxNew[MESSAGES_ME], sizeof(DWORD));
			g_dwMsgMax[MESSAGES_ME] = g_dwMsgMaxNew[MESSAGES_ME];
		}

		if (lstrcmp(g_szMsgStoreNew[MESSAGES_ME], g_szMsgStore[MESSAGES_ME]) != 0)
		{
			lstrcpy(szProvider, g_szMsgStoreNew[MESSAGES_ME]);
			dwSize = (lstrlen(szProvider) + 1)*sizeof(TCHAR);
			RegSetValueEx(hKey, ME_MSG_STORE, 0, REG_SZ, (LPBYTE) &szProvider, dwSize);
			if (g_szMsgStore[MESSAGES_ME] != NULL)
			{
				LocalFree(g_szMsgStore[MESSAGES_ME]);
				g_szMsgStore[MESSAGES_ME] = (TCHAR *)LocalAlloc(LPTR, dwSize);
				memcpy(g_szMsgStore[MESSAGES_ME], szProvider, dwSize);
			}
		}
		if (g_bAllMsgsNew[MESSAGES_SM] != g_bAllMsgs[MESSAGES_SM])
		{
			RegSetValueEx(hKey, SM_ALL_MSGS, 0, REG_DWORD, (LPBYTE) &g_bAllMsgsNew[MESSAGES_SM], sizeof(DWORD));
			g_bAllMsgs[MESSAGES_SM] = g_bAllMsgsNew[MESSAGES_SM];
		}

		if (g_dwMsgMaxNew[MESSAGES_SM] != g_dwMsgMax[MESSAGES_SM])
		{
			RegSetValueEx(hKey, SM_MSG_MAX, 0, REG_DWORD, (LPBYTE) &g_dwMsgMaxNew[MESSAGES_SM], sizeof(DWORD));
			g_dwMsgMax[MESSAGES_SM] = g_dwMsgMaxNew[MESSAGES_SM];
		}

		if (lstrcmp(g_szMsgStoreNew[MESSAGES_SM], g_szMsgStore[MESSAGES_SM]) != 0)
		{
			lstrcpy(szProvider, g_szMsgStoreNew[MESSAGES_SM]);
			dwSize = (lstrlen(szProvider) + 1)*sizeof(TCHAR);
			RegSetValueEx(hKey, SM_MSG_STORE, 0, REG_SZ, (LPBYTE) &szProvider, dwSize);
			if (g_szMsgStore[MESSAGES_SM] != NULL)
			{
				LocalFree(g_szMsgStore[MESSAGES_SM]);
				g_szMsgStore[MESSAGES_SM] = (TCHAR *)LocalAlloc(LPTR, dwSize);
				memcpy(g_szMsgStore[MESSAGES_SM], szProvider, dwSize);
			}
		}
		RegCloseKey(hKey);
	}
}

void WriteFeatureSettings()
{
    HRESULT hr                  = S_OK;
    HKEY    hKey                = NULL;
    DWORD   dwType              = 0;
	DWORD	dwSize				= 0;
	DWORD	dwValue				= 0;

    if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, JETWARE_KEY, 0, NULL, 0, 0, NULL, &hKey, &dwType))
	{
		if (g_dwHandleCPBS != CMD_LOCAL_ONLY)
			RegSetValueEx(hKey, HANDLE_CPBS, 0, REG_DWORD, (LPBYTE) &g_dwHandleCPBS, sizeof(DWORD));
		else
			RegDeleteValue(hKey, HANDLE_CPBS);

		if (g_dwHandleCPMS != CMD_LOCAL_ONLY)
			RegSetValueEx(hKey, HANDLE_CPMS, 0, REG_DWORD, (LPBYTE) &g_dwHandleCPMS, sizeof(DWORD));
		else
			RegDeleteValue(hKey, HANDLE_CPMS);

		if (g_dwHandleCMER != CMD_BOTH)
			RegSetValueEx(hKey, HANDLE_CMER, 0, REG_DWORD, (LPBYTE) &g_dwHandleCMER, sizeof(DWORD));
		else
			RegDeleteValue(hKey, HANDLE_CMER);

		if (g_dwHandleCIND != CMD_BOTH)
			RegSetValueEx(hKey, HANDLE_CIND, 0, REG_DWORD, (LPBYTE) &g_dwHandleCIND, sizeof(DWORD));
		else
			RegDeleteValue(hKey, HANDLE_CIND);

		if (g_dwHandleCLIP != CMD_INTERNAL_ONLY)
			RegSetValueEx(hKey, HANDLE_CLIP, 0, REG_DWORD, (LPBYTE) &g_dwHandleCLIP, sizeof(DWORD));
		else
			RegDeleteValue(hKey, HANDLE_CLIP);

		if (g_dwHandleCHUP != CMD_BOTH)
			RegSetValueEx(hKey, HANDLE_CHUP, 0, REG_DWORD, (LPBYTE) &g_dwHandleCHUP, sizeof(DWORD));
		else
			RegDeleteValue(hKey, HANDLE_CHUP);

		if (g_dwInBandRing != TRUE)
			RegSetValueEx(hKey, IN_BAND_RING, 0, REG_DWORD, (LPBYTE) &g_dwInBandRing, sizeof(DWORD));
		else
			RegDeleteValue(hKey, IN_BAND_RING);

		if (g_dwHandleCKPD != CMD_INTERNAL_ONLY)
			RegSetValueEx(hKey, HANDLE_CKPD, 0, REG_DWORD, (LPBYTE) &g_dwHandleCKPD, sizeof(DWORD));
		else
			RegDeleteValue(hKey, HANDLE_CKPD);

		if (g_dwSleepOnDisconnect != 0)
			RegSetValueEx(hKey, SLEEP_ON_DISCONNECT, 0, REG_DWORD, (LPBYTE) &g_dwSleepOnDisconnect, sizeof(DWORD));
		else
			RegDeleteValue(hKey, SLEEP_ON_DISCONNECT);

		RegCloseKey(hKey);
	}
}

void SetLogging(DWORD dwLogLevel)
{
    HRESULT hr                  = S_OK;
    HKEY    hKey                = NULL;
    DWORD   dwType              = 0;
	DWORD	dwSize				= 0;
	DWORD	dwValue				= dwLogLevel;

	g_wDebugLevels = (WORD) dwLogLevel;

    if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, JETWARE_KEY, 0, NULL, 0, 0, NULL, &hKey, &dwType))
	{
		if (dwLogLevel)
			RegSetValueEx(hKey, DEBUGLEVEL, 0, REG_DWORD, (LPBYTE) &dwValue, sizeof(DWORD));
		else
			RegDeleteValue(hKey, DEBUGLEVEL);

		RegCloseKey(hKey);
	}
}

void GetRegSettings()
{
    HRESULT hr                  = S_OK;
    HKEY    hKey                = NULL;
    DWORD   dwType              = 0;
	DWORD	dwSize				= 0;
	DWORD	wValue				= 0;
	TCHAR	szValue[256];
#ifdef DEBUG
	CHAR szLog[256];
#endif

    if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_LOCAL_MACHINE, JETWARE_KEY, 0, NULL, 0, 0, NULL, &hKey, &dwType))
		goto Error;

	// read in-band ringtone support
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, IN_BAND_RING, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwInBandRing = wValue;
	else
		g_dwInBandRing = TRUE;
	// read sleep-on-disconnect support
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, SLEEP_ON_DISCONNECT, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwSleepOnDisconnect = wValue;
	else
		g_dwSleepOnDisconnect = FALSE;
	// read feature mask
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, FEATUREMASK, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwFeatureMask = wValue;
    // Get debug logging flags
	dwSize = sizeof(DWORD);
    RegQueryValueEx(hKey, DEBUGLEVEL, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
	{
		g_wDebugLevels = (WORD) wValue;
	}
	// Read filter string for categories of contacts to send to phone
	dwSize = sizeof(szValue);
	dwType = 0;
    if (ERROR_SUCCESS == RegQueryValueEx(hKey, PBFILTER, NULL, &dwType, (LPBYTE) &szValue, &dwSize))
	{
		if (dwSize && (dwType == REG_SZ))
		{
			if (g_szContactFilter != NULL)
				LocalFree(g_szContactFilter);
			g_szContactFilter = (TCHAR *)LocalAlloc(LPTR, dwSize);
			memcpy(g_szContactFilter, szValue, dwSize);
#ifdef DEBUG
			sprintf(szLog, "\tContact filter=%ls Len=%i", g_szContactFilter, dwSize);
			LogString(szLog);
#endif
		}
		else if (g_szContactFilter != NULL)
		{
			LocalFree(g_szContactFilter);
			g_szContactFilter = NULL;
#ifdef DEBUG
			strcpy(szLog, "\tClearing contact filter");
			LogString(szLog);
#endif
		}
	}
	else if (g_szContactFilter != NULL)
	{
		LocalFree(g_szContactFilter);
		g_szContactFilter = NULL;
	}
	// read whether to include contacts with no categories in Outlook
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, INCLUDE_NOCAT, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_bIncludeNoCat = wValue;
	else
		g_bIncludeNoCat = FALSE;
	// Read settings for message access. Default: ME=ActiveSync, SM=SMS
	// read ME Store settings
	dwSize = sizeof(szValue);
	dwType = 0;
	if (g_szMsgStore[MESSAGES_ME] != NULL) // This should always be true
	{
		LocalFree(g_szMsgStore[MESSAGES_ME]);
		g_szMsgStore[MESSAGES_ME] = NULL;
	}
    if (ERROR_SUCCESS == RegQueryValueEx(hKey, ME_MSG_STORE, NULL, &dwType, (LPBYTE) &szValue, &dwSize))
	{
		if (dwSize && (dwType == REG_SZ))
		{
			g_szMsgStore[MESSAGES_ME] = (TCHAR *)LocalAlloc(LPTR, dwSize);
			memcpy(g_szMsgStore[MESSAGES_ME], szValue, dwSize);
		}
	}
	if (g_szMsgStore[MESSAGES_ME] == NULL) // Nothing in the registry, use default
	{
		g_szMsgStore[MESSAGES_ME] = (TCHAR *)LocalAlloc(LPTR, 24);
		lstrcpy(g_szMsgStore[MESSAGES_ME], _T("ActiveSync"));
	}
#ifdef DEBUG
	sprintf(szLog, "\tME message store=%ls", g_szMsgStore[MESSAGES_ME]);
	LogString(szLog);
#endif
	// read max messages for ME
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, ME_MSG_MAX, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwMsgMax[MESSAGES_ME] = wValue;
	// read whether to include read messages from ME store
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, ME_ALL_MSGS, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_bAllMsgs[MESSAGES_ME] = wValue;
	// Read SM store settings
	dwSize = sizeof(szValue);
	dwType = 0;
	if (g_szMsgStore[MESSAGES_SM] != NULL) // This should always be true
	{
		LocalFree(g_szMsgStore[MESSAGES_SM]);
		g_szMsgStore[MESSAGES_SM] = NULL;
	}
    if (ERROR_SUCCESS == RegQueryValueEx(hKey, SM_MSG_STORE, NULL, &dwType, (LPBYTE) &szValue, &dwSize))
	{
		if (dwSize && (dwType == REG_SZ))
		{
			g_szMsgStore[MESSAGES_SM] = (TCHAR *)LocalAlloc(LPTR, dwSize);
			memcpy(g_szMsgStore[MESSAGES_SM], szValue, dwSize);
		}
	}
	if (g_szMsgStore[MESSAGES_SM] == NULL) // Nothing in the registry, use default
	{
		g_szMsgStore[MESSAGES_SM] = (TCHAR *)LocalAlloc(LPTR, 8);
		lstrcpy(g_szMsgStore[MESSAGES_SM], _T("SMS"));
	}
#ifdef DEBUG
	sprintf(szLog, "\tSM message store=%ls", g_szMsgStore[MESSAGES_SM]);
	LogString(szLog);
#endif
	// read max messages for ME
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, SM_MSG_MAX, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwMsgMax[MESSAGES_SM] = wValue;
	// read whether to include read messages from SM store
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, SM_ALL_MSGS, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_bAllMsgs[MESSAGES_SM] = wValue;
	// read whether to include fax numbers to HF devices
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, PBINCLUDE_FAX, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwIncludeFax = wValue;
	// read CMER handling
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, HANDLE_CMER, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwHandleCMER = wValue;
	// read CIND handling
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, HANDLE_CIND, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwHandleCIND = wValue;
	// read CLIP handling
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, HANDLE_CLIP, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwHandleCLIP = wValue;
	// read CHUP handling
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, HANDLE_CHUP, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwHandleCHUP = wValue;
	// read CKPD handling (Voice dialing)
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, HANDLE_CKPD, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwHandleCKPD = wValue;
	// read CPMS handling
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, HANDLE_CPMS, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwHandleCPMS = wValue;
	// read CPBS handling
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, HANDLE_CPBS, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwHandleCPBS = wValue;
	// read Outlook Phonebook limit
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, PBLIMIT_ME, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwMaxContacts[CONTACTS_ME] = wValue;
	else
		g_dwMaxContacts[CONTACTS_ME] = NO_LIMIT;
	// read SIM Phonebook limit
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, PBLIMIT_SM, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwMaxContacts[CONTACTS_SM] = wValue;
	else
		g_dwMaxContacts[CONTACTS_SM] = NO_LIMIT;
	// read Dialed Call Phonebook limit
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, PBLIMIT_DC, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwMaxContacts[CONTACTS_DC] = wValue;
	else
		g_dwMaxContacts[CONTACTS_DC] = NO_LIMIT;
	// read Recieved Call Phonebook limit
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, PBLIMIT_RC, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwMaxContacts[CONTACTS_RC] = wValue;
	else
		g_dwMaxContacts[CONTACTS_RC] = NO_LIMIT;
	// read Missed Call Phonebook limit
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, PBLIMIT_MC, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwMaxContacts[CONTACTS_MC] = wValue;
	else
		g_dwMaxContacts[CONTACTS_MC] = NO_LIMIT;
	// read ReportIMI option - controls response to AT+CIMI - 1=report true IMI, 2=mask subscriber ID
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, REPORT_IMI, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwReportIMI = wValue;
	// read Invert Roam option - Allows use of Roaming indicator on BMW to indicate connection
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, INVERTROAM, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if (dwSize && (dwType == REG_DWORD))
		g_dwInvertRoam = wValue;
	// read in-call polling interval in milliseconds
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, STATUSPOLL_INCALL, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if ((wValue > 0) && dwSize && (dwType == REG_DWORD))
		g_dwInCallInterval = wValue;
	// read idle polling interval in milliseconds
	dwSize = sizeof(DWORD);
	wValue = 0;
	dwType = 0;
    RegQueryValueEx(hKey, STATUSPOLL_IDLE, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
	if ((wValue > 0) && dwSize && (dwType == REG_DWORD))
		g_dwIdleInterval = wValue;

Error:
    if (NULL != hKey)
    {
        RegCloseKey(hKey);
    }
}

BOOL IsSupported()
{
	// Test for Microsoft BT stack - does it have btagsvc.dll
	// TODO: See if we can open device BAG0:
	HINSTANCE hDll = LoadLibrary(_T("btagsvc.dll"));
	if (hDll == NULL)
	{
		DWORD dwErr = GetLastError();
		if (dwErr == ERROR_FILE_NOT_FOUND)
		{
			return FALSE;
		}
	}
	else
		FreeLibrary(hDll);
	return TRUE;
}

BOOL IsInstalled()
{
    HRESULT hr                  = S_OK;
    HKEY    hKey                = NULL;
    DWORD   dwType              = 0;
	DWORD	dwSize				= 0;
	WORD	wValue				= 0;
	BOOL	bFoundKey			= FALSE;
	BOOL	bFound				= FALSE;
	TCHAR	szValue[256];
	HINSTANCE hDll = NULL;

	if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, RK_AUDIO_GATEWAY, 0, 0, &hKey))
		goto Error;

	// See if we were registered at install
	dwSize = sizeof(szValue);
	if (ERROR_SUCCESS == RegQueryValueEx(hKey, _T("JETwareModule"), NULL, &dwType, (LPBYTE) &szValue, &dwSize))
	{
		if (dwSize && (dwType == REG_SZ))
		{
			bFoundKey = TRUE;
		}
	}
	if (!bFoundKey)
	{
		// JETware module not in registry, see if it's in Program Files\JETware
		BOOL bRet = SHGetSpecialFolderPath(NULL, szValue, CSIDL_PROGRAM_FILES, FALSE);
		lstrcat(szValue, L"\\JETware\\JetBTHFx.dll");
	}
	hDll = LoadLibrary(szValue);
#ifdef DEBUG
	CHAR szLog[256];
	sprintf(szLog, "JETwareModule found=%i, path=%ls, handle=%8.8X", bFoundKey, szValue, hDll);
	LogString(szLog);
#endif
	if (hDll == NULL)
	{
		bFound = FALSE;
	}
	else
	{
		bFound = TRUE;
		if (!bFoundKey)
			RegSetValueEx(hKey, _T("JETwareModule"), 0, REG_SZ, (LPBYTE) &szValue, (lstrlen(szValue) + 1)*sizeof(TCHAR));

		FreeLibrary(hDll);
	}

Error:
	if (NULL != hKey)
	{
		RegCloseKey(hKey);
	}
	return bFound;
}

BOOL IsRegistered()
{
    HRESULT hr                  = S_OK;
    HKEY    hKey                = NULL;
    DWORD   dwType              = 0;
	DWORD	dwSize				= 0;
	WORD	wValue				= 0;
	BOOL	bFoundPBModule		= FALSE;
	BOOL	bFound				= FALSE;
	TCHAR	szValue[256];

	if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, RK_AUDIO_GATEWAY, 0, 0, &hKey))
		goto Error;

	// Get ext dll name, if one already exists
	// Try BTAGPBModule first - WM 5 devices will have that
	dwSize = sizeof(szValue);
	if (ERROR_SUCCESS == RegQueryValueEx(hKey, PBMODULE, NULL, &dwType, (LPBYTE) &szValue, &dwSize))
	{
		if (dwSize && (dwType == REG_SZ))
		{
			bFoundPBModule = TRUE;
			// Check to see if it is ours
			if (wcsstr(szValue, _T("JetBTHFx.dll")) != NULL)
			{
				bFound = TRUE;
			}
		}
	}
	if (!bFound)
	{
		// check EXTMODULE
		dwSize = sizeof(szValue);
		if (ERROR_SUCCESS == RegQueryValueEx(hKey, EXTMODULE, NULL, &dwType, (LPBYTE) &szValue, &dwSize))
		{
			if (dwSize && (dwType == REG_SZ))
			{
				if (wcsstr(szValue, _T("JetBTHFx.dll")) != NULL)
				{
					bFound = TRUE;
				}
			}
		}
	}
Error:
	if (NULL != hKey)
	{
		RegCloseKey(hKey);
	}
	return bFound;
}

BOOL IsRunning()
{
    HRESULT hr                  = S_OK;
    HKEY    hKey                = NULL;
    DWORD   dwType              = 0;
	DWORD	dwSize				= 0;
	WORD	wValue				= 0;
	BOOL	bFoundPBModule		= FALSE;
	BOOL	bFound				= FALSE;
	TCHAR	szValue[256];

	if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, RK_AUDIO_GATEWAY, 0, 0, &hKey))
		goto Error;

	// Get ext dll name, if one already exists
	// Try BTAGPBModule first - WM 5 devices will have that
	dwSize = sizeof(szValue);
	if (ERROR_SUCCESS == RegQueryValueEx(hKey, PBMODULE, NULL, &dwType, (LPBYTE) &szValue, &dwSize))
	{
		if (dwSize && (dwType == REG_SZ))
		{
			bFoundPBModule = TRUE;
			// Check to see if it is ours
			if (wcsstr(szValue, _T("JetBTHFx.dll")) != NULL)
			{
				bFound = TRUE;
			}
		}
	}
	if (!bFound)
	{
		// check EXTMODULE
		dwSize = sizeof(szValue);
		if (ERROR_SUCCESS == RegQueryValueEx(hKey, EXTMODULE, NULL, &dwType, (LPBYTE) &szValue, &dwSize))
		{
			if (dwSize && (dwType == REG_SZ))
			{
				if (wcsstr(szValue, _T("JetBTHFx.dll")) != NULL)
				{
					bFound = TRUE;
				}
			}
		}
	}
Error:
	if (NULL != hKey)
	{
		RegCloseKey(hKey);
	}

	if (bFound)
	{
		HANDLE h = CreateFile(szValue, GENERIC_READ | GENERIC_WRITE, 0,
			NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

		lstrcpy(g_szDllPath, szValue);

		if (h == INVALID_HANDLE_VALUE)
		{
			if (GetLastError() == ERROR_SHARING_VIOLATION)
				return TRUE;
			else
				return FALSE;
		}
		else
		{
			CloseHandle(h);
			return FALSE;
		}
	}
	return FALSE;
}

BOOL Register()
{
    HRESULT hr                  = S_OK;
    HKEY    hKey                = NULL;
    DWORD   dwType              = 0;
	DWORD	dwSize				= 0;
	WORD	wValue				= 0;
	BOOL	bFoundPBModule		= FALSE;
	BOOL	bRegistered			= FALSE;
	BOOL	bChainSet			= FALSE;
	TCHAR	szValue[256];

	if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, RK_AUDIO_GATEWAY, 0, 0, &hKey))
		goto Error;

	// see if chain is already set so we don't overwrite if it is
	dwSize = sizeof(szValue);
	if (ERROR_SUCCESS == RegQueryValueEx(hKey, PBMODULE, NULL, &dwType, (LPBYTE) &szValue, &dwSize))
	{
		if (dwSize && (dwType == REG_SZ))
		{
			bChainSet = TRUE;
		}
	}
	// Get ext dll name, if one already exists
	// Try BTAGPBModule first - WM 5 devices will have that
	dwSize = sizeof(szValue);
	if (ERROR_SUCCESS == RegQueryValueEx(hKey, PBMODULE, NULL, &dwType, (LPBYTE) &szValue, &dwSize))
	{
		if (dwSize && (dwType == REG_SZ))
		{
			bFoundPBModule = TRUE;
			// write it to chain setting
			if (!bChainSet)
				RegSetValueEx(hKey, CHAINMODULE, 0, REG_SZ, (LPBYTE) &szValue, (lstrlen(szValue) + 1)*sizeof(TCHAR));
			dwSize = sizeof(szValue);
			RegQueryValueEx(hKey, _T("JETwareModule"), NULL, &dwType, (LPBYTE) &szValue, &dwSize);
			RegSetValueEx(hKey, PBMODULE, 0, REG_SZ, (LPBYTE) &szValue, (lstrlen(szValue) + 1)*sizeof(TCHAR));
			bRegistered = TRUE;
		}
	}
	// else try the BTAGExtModule
	if (!bFoundPBModule && (ERROR_SUCCESS == RegQueryValueEx(hKey, EXTMODULE, NULL, &dwType, (LPBYTE) &szValue, &dwSize)))
	{
		if (dwSize && (dwType == REG_SZ))
		{
			// write it to chain setting
			if (!bChainSet)
				RegSetValueEx(hKey, CHAINMODULE, 0, REG_SZ, (LPBYTE) &szValue, (lstrlen(szValue) + 1)*sizeof(TCHAR));
			dwSize = sizeof(szValue);
			RegQueryValueEx(hKey, _T("JETwareModule"), NULL, &dwType, (LPBYTE) &szValue, &dwSize);
			RegSetValueEx(hKey, EXTMODULE, 0, REG_SZ, (LPBYTE) &szValue, (lstrlen(szValue) + 1)*sizeof(TCHAR));
			bRegistered = TRUE;
		}
	}
	if (!bRegistered)
	{
		dwSize = sizeof(szValue);
		RegQueryValueEx(hKey, _T("JETwareModule"), NULL, &dwType, (LPBYTE) &szValue, &dwSize);
		RegSetValueEx(hKey, EXTMODULE, 0, REG_SZ, (LPBYTE) &szValue, (lstrlen(szValue) + 1)*sizeof(TCHAR));
		bRegistered = TRUE;
	}

Error:
	if (NULL != hKey)
	{
		RegCloseKey(hKey);
	}
	return bRegistered;
}

BOOL RestartBAG()
{
	BOOL bRet = FALSE;
	HINSTANCE hDll = LoadLibrary(_T("coredll.dll"));
	if (hDll != NULL)
	{
		_GetServiceHandle * GetServiceHandle = (_GetServiceHandle *) GetProcAddress(hDll, _T("GetServiceHandle"));
		_DeregisterService * DeregisterService = (_DeregisterService *) GetProcAddress(hDll, _T("DeregisterService"));
		_RegisterService * RegisterService = (_RegisterService *) GetProcAddress(hDll, _T("RegisterService"));
		_ActivateService * ActivateService = (_ActivateService *) GetProcAddress(hDll, _T("ActivateService"));
		HANDLE hService = GetServiceHandle(L"BAG0:", NULL, NULL);
		if(INVALID_HANDLE_VALUE != hService)
		{
			 DeregisterService(hService);
			 // Don't know if DerigisterService is synchronous
			 Sleep(2000);
			 hService = ActivateService(_T("BTAGSVC"), 0);
			 // hService = RegisterService(_T("BAG"), 0, _T("BTAGSVC.dll"), 0);
	#ifdef DEBUG
			 CHAR szLog[64];
			 sprintf(szLog, "ActivateService returned 0x%8.8X", hService);
			 LogString(szLog);
	#endif
			 if (hService != INVALID_HANDLE_VALUE)
				 bRet = TRUE;
		}
		FreeLibrary(hDll);
	}
	return bRet;
}

BOOL RestartJPB()
{
	BOOL bRet = FALSE;
	HINSTANCE hDll = LoadLibrary(_T("coredll.dll"));
	if (hDll != NULL)
	{
		_GetServiceHandle * GetServiceHandle = (_GetServiceHandle *) GetProcAddress(hDll, _T("GetServiceHandle"));
		_DeregisterService * DeregisterService = (_DeregisterService *) GetProcAddress(hDll, _T("DeregisterService"));
		_RegisterService * RegisterService = (_RegisterService *) GetProcAddress(hDll, _T("RegisterService"));
		_ActivateService * ActivateService = (_ActivateService *) GetProcAddress(hDll, _T("ActivateService"));
		HANDLE hService = GetServiceHandle(L"JPB0:", NULL, NULL);
		if(INVALID_HANDLE_VALUE != hService)
		{
			 DeregisterService(hService);
			 // Don't know if DerigisterService is synchronous
			 Sleep(2000);
		}
		 hService = ActivateService(_T("Jetware"), 0);
		 // hService = RegisterService(_T("BAG"), 0, _T("BTAGSVC.dll"), 0);
#ifdef DEBUG
		 CHAR szLog[64];
		 sprintf(szLog, "ActivateService returned 0x%8.8X", hService);
		 LogString(szLog);
#endif
		 if (hService != INVALID_HANDLE_VALUE)
			 bRet = TRUE;
		FreeLibrary(hDll);
	}
	return bRet;
}
